#pragma once
#include "detail.hpp"
#include "fields.hpp"
#include "abstract.hpp"

namespace zl
{
    class JsonMessage : public BaseMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;

        virtual std::string serialize() override
        {
            std::string base_body;
            bool ret = JSON::serialize(m_body, base_body);
            if (ret)
            {
                return base_body;
            }
            else
            {
                return std::string();
            }
        }

        virtual bool unserialize(const std::string &body) override
        {
            return JSON::unserialize(body, m_body);
        }

    protected:
        Json::Value m_body;
    };

    class JsonRequest : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonRequest>;
    };

    class JsonResponse : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonResponse>;

        virtual bool check() override
        {
            // 响应 要判断响应状态码是否存在和类型是否正确
            if (m_body[KEY_RCODE].isNull() == true)
            {
                ELOG("响应中没有响应状态码");
                return false;
            }

            if (m_body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应状态码类型错误");
                return false;
            }
            return true;
        }

        virtual RCode rcode()
        {
            return (RCode)m_body[KEY_RCODE].asInt();
        }
        virtual void setRCode(RCode rcode)
        {
            m_body[KEY_RCODE] = (int)rcode;
        }
    };

    // 请求

    class RpcRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;

        virtual bool check() override
        {
            // rpc 请求方法名称--字符串 参数字段--对象
            if (m_body[KEY_METHOD].isNull() == true || m_body[KEY_METHOD].isString() == false)
            {
                ELOG("rpc请求中没有方法名称或者方法名称类型错误");
                return false;
            }
            if (m_body[KEY_PARAMS].isNull() || m_body[KEY_PARAMS].isObject() == false)
            {
                ELOG("rpc请求中没有参数或者参数类型错误");
                return false;
            }

            return true;
        }

        std::string method()
        {
            return m_body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &method_name)
        {
            m_body[KEY_METHOD] = method_name;
        }
        Json::Value params()
        {
            return m_body[KEY_PARAMS];
        }
        void setParams(const Json::Value &val)
        {
            m_body[KEY_PARAMS] = val;
        }
    };

    class TopicRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;
        virtual bool check() override
        {
            // 主题请求 要判断主题名称是否存在和类型是否正确
            if (m_body[KEY_TOPIC_KEY].isNull() == true || m_body[KEY_TOPIC_KEY].isString() == false)
            {
                ELOG("主题请求中没有服务名称或者主题名称类型错误");
                return false;
            }

            if (m_body[KEY_OPTYPE].isIntegral() == false || m_body[KEY_OPTYPE].isNull() == true)
            {
                ELOG("主题请求没有操作类型或者操作类型错误");
                return false;
            }
            if (m_body[KEY_OPTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH && (m_body[KEY_TOPIC_MSG].isNull() == true || m_body[KEY_TOPIC_MSG].isString() == false))
            {
                ELOG("主题消息发布没有消息内容或者内容类型错误");
                return false;
            }

            return true;
        }

        std::string topicKey()
        {
            return m_body[KEY_TOPIC_KEY].asString();
        }
        void setTopicKey(const std::string &key)
        {
            m_body[KEY_TOPIC_KEY] = key;
        }
        TopicOptype optype()
        {
            return (TopicOptype)m_body[KEY_OPTYPE].asInt();
        }
        void setOptype(TopicOptype optype)
        {
            m_body[KEY_OPTYPE] = (int)optype;
        }

        std::string topicMsg()
        {
            return m_body[KEY_TOPIC_MSG].asString();
        }
        void setTopicMsg(const std::string &msg)
        {
            m_body[KEY_TOPIC_MSG] = msg;
        }
    };

    typedef std::pair<std::string, int> Address;

    class ServiceRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;
        virtual bool check() override
        {
            // rpc请求中，包含请求方法名称-字符串，参数字段-对象
            if (m_body[KEY_METHOD].isNull() == true ||
                m_body[KEY_METHOD].isString() == false)
            {
                ELOG("服务请求中没有方法名称或方法名称类型错误！");
                return false;
            }
            if (m_body[KEY_OPTYPE].isNull() == true ||
                m_body[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("服务请求中没有操作类型或操作类型的类型错误！");
                return false;
            }
            if (m_body[KEY_OPTYPE].asInt() != (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                (m_body[KEY_HOST].isNull() == true ||
                 m_body[KEY_HOST].isObject() == false ||
                 m_body[KEY_HOST][KEY_HOST_IP].isNull() == true ||
                 m_body[KEY_HOST][KEY_HOST_IP].isString() == false ||
                 m_body[KEY_HOST][KEY_HOST_PORT].isNull() == true ||
                 m_body[KEY_HOST][KEY_HOST_PORT].isIntegral() == false))
            {
                ELOG("服务请求中主机地址信息错误！");
                return false;
            }
            return true;
        }

        std::string method()
        {
            return m_body[KEY_METHOD].asString();
        }
        void setMethod(const std::string &name)
        {
            m_body[KEY_METHOD] = name;
        }
        ServiceOptype optype()
        {
            return (ServiceOptype)m_body[KEY_OPTYPE].asInt();
        }
        void setOptype(ServiceOptype optype)
        {
            m_body[KEY_OPTYPE] = (int)optype;
        }
        Address host()
        {
            Address addr;
            addr.first = m_body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = m_body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }
        void setHost(const Address &host)
        {
            Json::Value val;
            val[KEY_HOST_IP] = host.first;
            val[KEY_HOST_PORT] = host.second;
            m_body[KEY_HOST] = val;
        }
    };

    // 响应
    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;

        virtual bool check() override
        {
            // rpc 请求方法名称--字符串 参数字段--对象
            if (m_body[KEY_RCODE].isNull() == true || m_body[KEY_RCODE].isIntegral() == false)
            {
                ELOG("响应中没有响应状态码或者状态码类型错误");
                return false;
            }
            if (m_body[KEY_RESULT].isNull()==true)
            {
                ELOG("响应中没有RCP调用或者类型错误");
                return false;
            }

            return true;
        }

        Json::Value result()
        {
            return m_body[KEY_RESULT];
        }
        void setresult(const Json::Value &result)
        {
            m_body[KEY_RESULT] = result;
        }
    };

    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
    };

    class ServiceResponse : public JsonResponse
    {

    public:
        using ptr = std::shared_ptr<ServiceResponse>;

        virtual bool check() override
        {

            if (m_body[KEY_METHOD].isNull() == true || m_body[KEY_METHOD].isString() == false)
            {
                ELOG("响应中没有响应状态码或者状态码类型错误");
                return false;
            }
            if (m_body[KEY_OPTYPE].isNull() == true ||
                m_body[KEY_OPTYPE].isIntegral() == false)
            {
                ELOG("响应中没有操作类型或者操作类型错误");
                return false;
            }
            if (m_body[KEY_OPTYPE].asInt() == (int)(ServiceOptype::SERVICE_DISCOVERY) &&
                (m_body[KEY_METHOD].isNull() == true || m_body[KEY_METHOD].isString() == false || m_body[KEY_HOST].isNull() == true || m_body[KEY_HOST].isArray() == false))
            {
                ELOG("服务响应中主机地址信息错误！");
                return false;
            }

            return true;
        }

        ServiceOptype optype()
        {
            return (ServiceOptype)m_body[KEY_OPTYPE].asInt();
        }
        void setOptype(ServiceOptype optype)
        {
            m_body[KEY_OPTYPE] = (int)optype;
        }
        std::string method()
        {
            return m_body[KEY_METHOD].asString();
        }
        void setMethod(const std::string& method)
        {
             m_body[KEY_METHOD]=method;
        }
        void setHost(std::vector<Address> addrs)
        {
            for (auto &addr : addrs)
            {
                Json::Value val;
                val[KEY_HOST_IP] = addr.first;
                val[KEY_HOST_PORT] = addr.second;
                m_body[KEY_HOST].append(val);
            }
        }

        std::vector<Address> hosts()
        {
            std::vector<Address> addrs;
            for (auto &addr : m_body[KEY_HOST])
            {
                addrs.push_back(std::make_pair(addr[KEY_HOST_IP].asString(), addr[KEY_HOST_PORT].asInt()));
            }
            return addrs;
        }
    };

    // 消息对象工厂
    class MessageFactory
    {
    public:
        static BaseMessage::ptr create(MType mtype)
        {
            switch (mtype)
            {
            case MType::REQ_RPC:
                return std::make_shared<RpcRequest>();
            case MType::RSP_RPC:
                return std::make_shared<RpcResponse>();
            case MType::REQ_TOPIC:
                return std::make_shared<TopicRequest>();
            case MType::RSP_TOPIC:
                return std::make_shared<TopicResponse>();
            case MType::REQ_SERVICE:
                return std::make_shared<ServiceRequest>();
            case MType::RSP_SERVICE:
                return std::make_shared<ServiceResponse>();
            }
            return BaseMessage::ptr();
        }

        template <typename T, typename... Args>
        // 创建并返回一个类型为T的智能指针对象
        // 该函数使用了完美转发，以保持函数参数的原始类型
        // 参数: Args&&... args: 可变参数模板，允许传递任意数量和类型的参数
        // 返回值: std::shared_ptr<T>: 返回一个指向新创建的T类型对象的智能指针
        static std::shared_ptr<T> create(Args &&...args)
        {
            // 使用std::make_shared来创建智能指针，它更加高效且不易出错
            // 使用std::forward将参数完美转发给新对象的构造函数，保持参数的原有属性
            return std::make_shared<T>(std::forward<Args>(args)...);
        }
    };
}